/**
 * 路由解析
 * 		格式化: {}外为原uri,内为处理追加  p>n:表示路径层级
 * 			/{main/index}  /p>0/{index}  /p=1{/index}  /p>1
 * @param uri string 路径  可含后缀(先提取,后匹配重新)
 * 		限制: a-z0-9_/组成,  /分割首尾不能是_,  _后必需a-z
 * @param rewrite array|null 路由重写 [[k,v],...]
 * 		k: RegExp|string 匹配查询  格式化后格式
 *			RegExp: 正则匹配  重写为: fmt.replace(k, v)
 *			'^'开头:前缀匹配, '='开头:相同匹配, 其他:包含匹配
 *		v: string 重写目标  若带?参数, 解析在返回.que={}
 * @return Object {src, fmt, ctr, act, ext, que, err}
 * 		src:原始URI,  fmt:格式化及重写后URI(小写)
 * 		ctr:控制器路径,  act:动作方法名(fmt末级)
 * 		ext:后缀(小写,无.),  que:重写参数{}|null
 * 		err: 异常 -> null, 'ctr', 'act', 'ext'
 * 			额外.自定义: path, file, call
 */
$.router = function(uri, rewrite=null){
	let [u,x]=$.path('/'+uri).toLowerCase().split('.');
	if(u.at(-1)==='/') u = (u==='/'?'/main/':u)+'index';
	else u = u.split('/').length===2 ? u+'/index' : u;
	let re=null, que=null, err=null;
	if(rewrite){
		for(let i=0,L=rewrite.length; i<L; i++){
			let [k,v]=rewrite[i];
			if(k instanceof RegExp)
				re = k.test(u) ? u.replace(k,v) : null;
			else if(k[0]==='^')
				re = u.startsWith(k.slice(1)) ? v : null;
			else if(k[0]==='=') re=k.slice(1)===u?v:null;
			else re = u.indexOf(k) ? v : null;
			if(re!==null) break;
		}
		if(re){
			let [p,q]=re.split('?'); p=$.path(p).toLowerCase();
			if(q) que = require('node::querystring').parse(q);
			if(u.at(-1)==='/') u = (p==='/'?'/main':u)+'index';
			else u = p.split('/').length===2 ? p+'/index' : p;
		}
	}
	let s=u.split('/'), act=s.pop(), ctr=s.join('/');
	if(/(\/_|_\/|__|_\d|_$)/.test(ctr)) err='ctr';
	else if(/[^a-z\d_\/]/.test(ctr)) err = 'pre';
	else if(!/^[a-z][a-z\d_]*$/.test(act)) err='act';
	else if(x && !/^[a-z]+$/.test(x)) err = 'ext';
	return {src:uri,fmt:u,ctr,act,ext:x||'',que,err};
};
